/*
 * Exploder
 * 
 * Tero Pyylampi (218437), Jussi Tuurinkoski (211594)
 *
 * Abstract base class for all the border elements in the game
 */

#include "GameBorder.h"
#include "../../../GameCamera.h"
#include "../../../effects/GameEffects.h"
#include "../../../../Resources.h"
#include "../../../../Common.h"

using namespace cocos2d;

// default constructor
GameBorder::GameBorder( b2World *world, cocos2d::CCLayer *layer, GameCamera *camera, float durability )
	: GamePhysicObject( world ), mGameLayer( layer ), mGameCamera( camera ), mMaxDurability( durability ), 
	mDurabilityLeft( durability ), mBrokenSpriteInUse( false ), mBorderDestroyed( false ), mBorderMenu( 0 ) {
	
	mBorderMenu = CCMenu::node();
	layer->addChild( mBorderMenu, Z_LAYER_INTERFACE );
	createBorderMenuItems();
}

// default destructor
GameBorder::~GameBorder() {
	// remove sprite(s)
	if( mGameLayer->getChildren()->containsObject( mBrokenSprite ) )
		mGameLayer->removeChild( mBrokenSprite, true );
	if( mGameLayer->getChildren()->containsObject( mBorderSprite ) ) {
		mGameLayer->removeChild( mBorderSprite, true );
		mBrokenSprite->release();
	}
	if( mBorderMenu != 0 )
		mGameLayer->removeChild( mBorderMenu, true );
}

// default update function
void GameBorder::update( cocos2d::ccTime dt ) {
	GamePhysicObject::update( dt );

	// destroy
	if( mDurabilityLeft <= 0.0f && mBorderDestroyed == false ) {
		mBorderDestroyed = true;
		breakObject();
	}
	// change sprite
	else if( mDurabilityLeft <= mMaxDurability * 0.5f && mBrokenSpriteInUse == false ) {
		mBrokenSpriteInUse = true;
		changeToBrokenSprite();
	}

	// normal update method
	if( ! mBorderDestroyed ) {
		// calculate sprite position & rotation
		b2Vec2 myWorldPos = mBodies->at( 0 )->GetPosition();
		cocos2d::CCPoint myScreenPos = mGameCamera->convertWorldToScreen( myWorldPos.x, myWorldPos.y );
		float myRotation = mBodies->at( 0 )->GetAngle() * -180.0f / 3.14159f;

		// set properties
		if( mBrokenSpriteInUse ) {
			mBrokenSprite->setPosition( myScreenPos );
			mBrokenSprite->setRotation( myRotation );
			mBorderMenu->setPosition( myScreenPos );
		}
		else {
			mBorderSprite->setPosition( myScreenPos );
			mBorderSprite->setRotation( myRotation );
			mBorderMenu->setPosition( myScreenPos );
		}
	}
}

// object takes damage as a result of a collision
void GameBorder::takeDamage( float damage, b2Body *bodyTakingDamage ) {
	if( mDurabilityLeft > 0.0f ) {
		mDurabilityLeft -= damage;
	}
}

// break and remove object
void GameBorder::breakObject() {
	// remove meny
	mGameLayer->removeChild( mBorderMenu, true );
	mBorderMenu = 0;

	// default breaking method
	mBorderDestroyed = true;
	
	// cause explosion effect
	cocos2d::CCPoint pos = mBrokenSpriteInUse ? mBrokenSprite->getPosition() : mBorderSprite->getPosition();
	cocos2d::CCParticleSystem *s = GameEffects::createSmokeEffect( pos.x, pos.y );
	mGameLayer->addChild( s, Z_LAYER_GAME_EFFECTS );

	// remove sprite(s)
	if( mGameLayer->getChildren()->containsObject( mBrokenSprite ) )
		mGameLayer->removeChild( mBrokenSprite, true );
	mBrokenSprite = 0;
	if( mGameLayer->getChildren()->containsObject( mBorderSprite ) ) {
		mGameLayer->removeChild( mBorderSprite, true );
		mBrokenSprite->release();
	}
	mBorderSprite = 0;

	// remove physic object
	mGameWorld->DestroyBody( mBodies->at( 0 ) );
	mBodies->clear();
}

// change to broken sprite
void GameBorder::changeToBrokenSprite() {
	// remove old sprite from layer
	if( mGameLayer->getChildren()->containsObject( mBorderSprite ) )
		mGameLayer->removeChild( mBorderSprite, true );
	mBorderSprite = 0;

	// add new one
	mGameLayer->addChild( mBrokenSprite, Z_LAYER_GAME_MIDDLE );
	mBrokenSprite->release();

	// update to match position
	update( 0 );
}

// get the main type of the object
PhysicObjectItems GameBorder::getObjectType() {
	return BORDER_INVALID;
}

// get absolute screen position of the sprite
cocos2d::CCPoint GameBorder::getObjectScreenPosition() {
	if( mBrokenSpriteInUse )
		return mGameLayer->convertToWorldSpace( mBrokenSprite->getPosition() );
	else
		return mGameLayer->convertToWorldSpace( mBorderSprite->getPosition() );
}

// rotate item
void GameBorder::rotateItem( cocos2d::CCObject *pSender ) {
	mBodies->at( 0 )->SetTransform( mBodies->at( 0 )->GetPosition(), mBodies->at( 0 )->GetAngle() - 3.14159265359f / 8.0f );
}

// helper function to create menu items
void GameBorder::createBorderMenuItems() {
	// rotate button
	CCMenuItemImage *rotateItemCWButton = CCMenuItemImage::itemFromNormalImage( getResource( Textures::GAME_INTERFACE_ROTATE ), getResource( Textures::GAME_INTERFACE_ROTATE_PRESSED ), this, menu_selector( GameBorder::rotateItem ) );
	rotateItemCWButton->setScale( RATEX * 0.3f );
	rotateItemCWButton->setPosition( WIN_WIDTH * 0.04f, -WIN_HEIGHT * 0.05f );
	mBorderMenu->addChild( rotateItemCWButton, 0 );
}
